#include "databasemanager.h"
#include "databasemanager.h"
#include <QDebug>
#include <QDateTime>
#include <QStringBuilder>
#include <string>
#include <qregularexpression.h>
#include <QByteArray>
#include <QMutexLocker>

// 宏定义放在.cpp中（不污染头文件）
#define SERIALIZE(funcName, ...) \
[&]() { \
        QString data = funcName; \
        QVector<QString> params = {__VA_ARGS__}; \
        for (const auto& param : params) { \
        data += "|" + param; \
    } \
        return data; \
}()

DatabaseManager &DatabaseManager::getInstance()
{
    static DatabaseManager instance;
    return instance;
}

QSqlDatabase DatabaseManager::getDatabase() const
{
    return db;
}

int DatabaseManager::insert_register(const QString &nickname, const QString &password, const QString &phone, const QString &email)
{
    QVector<QString> params = {};
    QString operationId = generateOperationId("insert_register", params);
    // 发送请求
    send("insert_register", nickname, password,phone,email);
    // 开始阻塞（假设超时10秒）
    startBlocking(operationId, 10000);
    auto response=getResult<QString>(operationId);
    if(response!="")
    return 1;
    return 0;
}

std::tuple<QString,QString,QString> DatabaseManager::query_login(const QString &username,const QString& password)
{
    QVector<QString> params = {};
    QString operationId = generateOperationId("query_login_1", params);
    // 发送请求
    send("query_login_1", username, password);
    // 开始阻塞（假设超时10秒）
    startBlocking(operationId, 10000);
    // 这里可以根据需要设置返回值，假设从其他地方获取结果
    auto response= getResult<std::tuple<QString, QString, QString>>(operationId);

    if(!(std::get<0>(response).isEmpty()))
    {
            QVector<QString> params = {};
            QString tmpId = generateOperationId("update_login", params);

            return {std::get<0>(response),std::get<1>(response),std::get<2>(response)};
    }else{
        return {"账号或密码有问题","",""};
    }
}

std::tuple<QString, QString, QString> DatabaseManager::query_login(const QString &username)
{
    QSqlQuery query(db);
    qDebug()<<username;
    query.prepare("select nickname,avatar,last_login_time from user_info where username= :username ");
    query.bindValue(":username",username.toInt());
    if (!query.exec()) {
        qDebug() << "SQL执行错误:" << query.lastError().text();
        return {"SQL执行错误","",""}; // 返回特殊错误码
    }
    if(query.next())
    {

            QSqlQuery update(db);
            QDateTime current_date_time =QDateTime::currentDateTime();
            update.prepare("update user_info set status=1,last_login_time=:current_date_time where username= :username");
            update.bindValue(":current_date_time",current_date_time);
            update.bindValue(":username",username);
            update.exec();
            return {query.value(0).toString(),query.value(1).toString(),query.value(2).toString()};
    }

    return {"","",""};
}

bool DatabaseManager::close_login(const QString &username)
{
    QVector<QString> params={};
    QString operationId=generateOperationId("close_login",params);

    //发送请求
    send("close_login",username);

    startBlocking(operationId,10000);
    auto response=getResult<QString>(operationId);
    if(response=="success")
    {
        return true;
    }
    return false;
}

bool DatabaseManager::CloseUserStatus(const QString& username)
{
    QSqlQuery update(db),query(db);
    qDebug()<<"username"<<username;
    update.prepare("update user_info set status=0 where username= :username");
    update.bindValue(":username",username);
    if(!update.exec())
        qDebug()<<query.lastError().text();
    query.prepare("select status from user_info where username= :username");
    query.bindValue(":username",username);
    query.exec();
    if(query.next())
    {
        if(query.value(0).toInt()==0)
        {
            return true;
        }
    }
    return false;
}

QVector<std::tuple<QString,QString,QString>> DatabaseManager::query_path(const QString &id)
{
    QSqlQuery query(db);
    query.prepare("select avatar,username,nickname"
                  " from user_info"
                  " where username in("
                  " select distinct friend_id"
                  " from ("
                  " select user2 as friend_id"
                  " from private_member"
                  " where user1 = :id and relationship_type in (0,1)"
                  " union all"
                  " select user1 as friend_id"
                  " from private_member"
                  " where user2 = :id and relationship_type in (0,1)"
                  " )as combined_query"
                  " );");
    query.bindValue(":id",id.toInt());
    QVector<std::tuple<QString,QString,QString>> qvec;
    query.exec();
    while(query.next())
    {
        std::tuple<QString,QString,QString> tmp(query.value(0).toString(),query.value(1).toString(),query.value(2).toString());
        qvec.push_back(tmp);
    }
    return qvec;

}

QVector<std::tuple<QString, QString, QString,int>> DatabaseManager::query_request(const QString &id,const QString &goal)
{
    QSqlQuery query(db);
    if(goal.isEmpty()){
        query.prepare(" select avatar,username,nickname,pm.who_request "
                      " from user_info ui"
                      " LEFT JOIN private_member pm "
                      " ON ui.username = pm.user1  "
                      "  AND pm.user2 = :id "
                      " where username in( "
                      " select user1 "
                      " from private_member "
                      " WHERE user2 = :id "
                      "); ");
        query.bindValue(":id",id.toInt());
        QVector<std::tuple<QString,QString,QString,int>> qvec;
        query.exec();
        while(query.next())
        {
            std::tuple<QString,QString,QString,int> tmp(query.value(0).toString(),query.value(1).toString(),query.value(2).toString(),query.value(3).toInt());
            qvec.push_back(tmp);
        }
        return qvec;
    }else {
        query.prepare("select pm.`who_request` from private_member pm where user1=:user1 and user2=:user2;");
        query.bindValue(":user1",id.toInt());
        query.bindValue(":user2",goal.toInt());
        QVector<std::tuple<QString,QString,QString,int>> qvec;
        query.exec();
        if(query.next())
        {
            std::tuple<QString,QString,QString,int> tmp("","","",query.value(0).toInt());
            qvec.push_back(tmp);
        }
        return qvec;
    }
}

QVector<std::tuple<QString, QString, QString,int>> DatabaseManager::query_send_request(const QString &id,const QString& goal)
{
    QSqlQuery query(db);
    if(goal.isEmpty()){
        query.prepare("select avatar,username,nickname,pm.who_request"
                      " from user_info"
                      " join private_member pm"
                      " on user_info.username=pm.user2"
                      "  AND pm.user1 = :id "
                      "where username in("
                      " select user2"
                      " from private_member"
                      " where user1 = :id "
                      " );");
        query.bindValue(":id",id.toInt());
        QVector<std::tuple<QString,QString,QString,int>> qvec;
        query.exec();
        while(query.next())
        {
            std::tuple<QString,QString,QString,int> tmp(query.value(0).toString(),query.value(1).toString(),query.value(2).toString(),query.value(3).toInt());
            qvec.push_back(tmp);
        }
        return qvec;
    }else
    {
        query.prepare("select pm.who_request from private_member pm where user1=:user1 and user2=:user2;");
        query.bindValue(":user1",goal.toInt());
        query.bindValue(":user2",id.toInt());
        QVector<std::tuple<QString,QString,QString,int>> qvec;
        query.exec();
        if(query.next())
        {
            std::tuple<QString,QString,QString,int> tmp("","","",query.value(0).toInt());
            qvec.push_back(tmp);
        }
        return qvec;
    }
}


bool DatabaseManager::PrivateSendMsg(const QString &id_1, const QString &id_2, const QString &text)
{

    QSqlQuery query(db);
    qDebug()<<"id_1"<<id_1;
    qDebug()<<"id_2"<<id_2;
    // 先尝试查询 user1=id_1, user2=id_2 的记录
    query.prepare("SELECT text_count, relationship_type FROM private_member WHERE user1=:user1 AND user2=:user2");
    query.bindValue(":user1", id_1.toInt());
    query.bindValue(":user2", id_2.toInt());

    if (!query.exec()) {
        qDebug() << "执行查询失败:" << query.lastError().text();
        return false;
    }

    // 如果没有找到记录，尝试交换用户再查询
    if (!query.next()) {
        query.prepare("SELECT text_count, relationship_type FROM private_member WHERE user1=:user1 AND user2=:user2");
        query.bindValue(":user1", id_2.toInt());
        query.bindValue(":user2", id_1.toInt());

        if (!query.exec()) {
            qDebug() << "执行反向查询失败:" << query.lastError().text();
            return false;
        }

        // 如果反向查询也没有结果，返回false
        if (!query.next()) {
            qDebug() << "未找到相关记录";
            return false;
        }
    }

    // 正确读取两个字段的值
    int text_count = query.value(0).toInt(); // 第0列是text_count
    int type = query.value(1).toInt();       // 第1列是relation_ship

    // 业务逻辑判断
    if (type == 0 && text_count >= 6) {
        return false;
    }
    QSqlQuery update(db);
    update.prepare("update private_member set text_count=:text_count where user1=:user1 and user2=:user2");
    update.bindValue(":text_count",text_count+1);
    update.bindValue(":uesr1",id_1.toInt());
    update.bindValue(":user2",id_2.toInt());

    QVector<QString> params={};
    QString operationId=generateOperationId("insert_message",params);
    send("insert_message",id_1,id_2,0,text);
    startBlocking(operationId,10000);
    auto response=getResult<QString>(operationId);

    if(response!="")
    {
        if(!update.exec())
        {
            qDebug()<<"update text_count error";
        }
        QSqlQuery insert(db);
        insert.prepare("insert into private_message (sender_id,receiver_id,msg_type,content,send_time,is_deleted) "
                       " values(:id_1,:id_2,0,:content,:send_time,:is_deleted)");
        insert.bindValue(":id_1",id_1.toInt());
        insert.bindValue(":id_2",id_2.toInt());
        insert.bindValue(":content",text);
        insert.bindValue(":send_time",response);
        insert.bindValue(":is_deleted",0);
        if(!insert.exec())
        {
            qDebug("insert Msg error");
        }
        return true;
    }

    return false;
}

QVector<QString> DatabaseManager::PrivateGetMsg(const QString &id_1, const QString &id_2, const QString &last_time)
{
    QSqlQuery query(db);
    QVector<QString> res;
    query.prepare("select content,send_time from private_message where sender_id =:id_1 and receiver_id=:id_2 and send_time> :last_time");
    query.bindValue(":id_1",id_1);
    query.bindValue(":id_2",id_2);
    query.bindValue(":last_time",last_time);
    if(!query.exec())
    {
        qDebug()<<"msg get error";
        return {};
    }
    while(query.next())
    {
        QString tmp=query.value(1).toString()+":";
        tmp+=query.value(0).toString();
        res.push_back(tmp);
    }
    return res;
}

int DatabaseManager::insert_request_or_member(int chat_type, int scale, const QString &id_1, const QString &id_2,const int type)
{
    QSqlQuery insert(db);
    if(scale==0)
    {
        QSqlQuery query(db),update(db);

        query.prepare("select id from private_member where user1=:user1 and user2=:user2");
        insert.prepare("insert into private_member (user1,user2,who_request,relationship_type,create_time,update_time,text_count) "
                       " values(:user1,:user2,:who_request,:relationship_type,:create_time,:update_time,0)");
        if(chat_type==0)
        {
            int textcount=0;

            query.bindValue(":user1",id_1.toInt());
            query.bindValue(":user2",id_2.toInt());

            if(!query.exec())
                return -1;
            if(query.next())
            {
                return 0;
            }
            query.bindValue(":user1",id_2.toInt());
            query.bindValue(":user2",id_1.toInt());
            if(!query.exec())
                return -1;
            if(query.next())
            {
                return 0;
            }

            QVector<QString> params={};
            QString operationId=generateOperationId("insert_request",params);
            send("insert_request",id_1,id_2,0,0);
            startBlocking(operationId,10000);
            auto response=getResult<std::tuple<QString,QString>>(operationId);
            if(!(std::get<0>(response).isEmpty()))
            {
                insert.bindValue(":user1",id_1.toInt());
                insert.bindValue(":user2",id_2.toInt());
                insert.bindValue(":who_request",0);
                insert.bindValue(":relationship_type",0);
                // QDateTime currentTime=QDateTime::currentDateTime();
                insert.bindValue(":create_time",std::get<0>(response));
                insert.bindValue(":update_time",std::get<1>(response));
                insert.bindValue(":text_count",0);
                if(!insert.exec())
                {
                    qDebug()<<"private_request insert error";
                }
                return 1;
            }


            return 0;
        }else if(chat_type==1)
        {
            bool is_insert=true;
            int ids=-1;
            query.bindValue(":user1",id_1.toInt());
            query.bindValue(":user2",id_2.toInt());
            if(!query.exec())
                return -1;
            if(query.next())
            {
                ids=query.value(0).toInt();
                is_insert=false;
            }
            query.bindValue(":user1",id_2.toInt());
            query.bindValue(":user2",id_1.toInt());
            if(!query.exec())
                return -1;
            if(query.next())
            {
                ids=query.value(0).toInt();
                is_insert=false;
            }
            if(is_insert)
            {
                QVector<QString> params={};
                QString operationId=generateOperationId("insert_request",params);
                send("insert_request",id_1,id_2,1,0);
                startBlocking(operationId,10000);
                auto response=getResult<std::tuple<QString,QString>>(operationId);
                if(!(std::get<0>(response).isEmpty()))
                {
                    insert.bindValue(":user1",id_1.toInt());
                    insert.bindValue(":user2",id_2.toInt());
                    insert.bindValue(":who_request",1);
                    insert.bindValue(":relationship_type",0);
                    QDateTime currentTime=QDateTime::currentDateTime();
                    insert.bindValue(":create_time",std::get<0>(response));
                    insert.bindValue(":update_time",std::get<1>(response));
                    insert.bindValue(":text_count",0);
                    if(!insert.exec())
                    {
                        qDebug()<<"private_request insert error";
                    }
                }
            }else {
                //这里先不做处理
                QVector<QString> params={};
                QString operationId=generateOperationId("update_request",params);
                send("update_request",type+1,type,ids);
                startBlocking(operationId,10000);
                auto response=getResult<QString>(operationId);
                if(response!="")
                {
                    update.prepare("update private_member set who_request=:who_re,relationship_type =:type where id=:id");
                    update.bindValue(":who_re",type+1);
                    update.bindValue(":type",type);
                    update.bindValue(":id",ids);
                    if(!update.exec())
                    {
                        qDebug()<<"private_member update error";
                    }
                    return 1;
                }
            }
            return 0;


        }
    }else {
        QSqlQuery query(db);
        query.prepare("select id from group_id where group_id=:group_id and applicant_id=:applicant_id");
        query.bindValue(":applicant_id",id_1);
        query.bindValue(":group_id",id_2);
        if(!query.exec())
            return -1;
        if(!query.next())
        {
            insert.prepare("insert into group_request (group_id,applicant_id,status,create_time,update_time) "
                           " values(:group_id,:applicant_id,1,:create_time,:update_time)");
            insert.bindValue(":group_id",id_2);
            insert.bindValue(":applicant_id",id_1);
            QDateTime currentTime=QDateTime::currentDateTime();
            insert.bindValue(":create_time",currentTime);
            insert.bindValue(":update_time",currentTime);
            if(!insert.exec())
            {
                qDebug()<<"group_request insert error";
            }
            return 1;
        }
    }
    return 0;
}

bool DatabaseManager::sendToServer(const QString &data)
{   
    qint64 bytesWritten =socket->write(data.toUtf8());
    socket->flush();
    if (bytesWritten == -1) {
        qDebug() << "写入失败:" << socket->errorString();
    } else {
        qDebug() << "已写入字节数:" << bytesWritten;
    }
    return true;
}



void DatabaseManager::recvServerMsg()
{
    QByteArray data = socket->readAll();
    QString msg = QString::fromUtf8(data);
     qDebug()<<"msg="<<msg;
    QStringList parts = msg.split('|');
    if (parts.isEmpty()) return;
    QString type = parts[0];
    QVector<QString> params;
    for (int i = 1; i < parts.size(); i++) {
        params.push_back(parts[i]);
    }
    // 根据消息类型生成操作标识并解除阻塞
    if(type=="insert_message")
    {
        QVector<QString> tmp={};
        QString operationId=generateOperationId("insert_message",tmp);
        if(params.size()>=1)
        {
            QString result=params[0];
            setResult(operationId,QVariant::fromValue(result));
        }
        stopBlocking(operationId);
    }else if(type=="insert_register")
    {
        QVector<QString> tmp={};
        QString operationId=generateOperationId("insert_register",tmp);
        if(params.size()>=1)
        {
            auto result=params[0];
            setResult(operationId,QVariant::fromValue(result));
        }
        stopBlocking(operationId);
    }else if(type=="update_request")
    {
        QVector<QString> tmp={};
        QString operationId=generateOperationId("update_request",tmp);
        if(params.size()>=1)
        {
            auto result=params[0];
            setResult(operationId,QVariant::fromValue(result));
        }
        stopBlocking(operationId);
    }else if(type=="selectMessage")
    {
        OnlineMsg(params[0],params[1],params[2],params[3],params[4],params[5],params[6]);
    }else if(type=="selectRequest")
    {
        OnlineReq(params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8],params[9]);
    }
    else if (type == "query_login_1") {
        QVector<QString> tmp={};
        QString operationId = generateOperationId("query_login_1", tmp);
        if (params.size() >= 3) {
            // 假设服务器返回的结果是用户名、昵称、头像等信息，按顺序组成元组
            auto result = std::make_tuple(params[0], params[1], params[2]);
            setResult(operationId, QVariant::fromValue(result));
        }
        stopBlocking(operationId);
    }
    else if (type == "update_login") {
        QVector<QString> tmp={};
        QString operationId = generateOperationId("update_login", tmp);
        if(params.size()>=1)
        {
            auto result=std::make_tuple(params[0]);
            setResult(operationId,QVariant::fromValue(result));
        }
        stopBlocking(operationId);
    }else if(type=="close_login")
    {
        QVector<QString> tmp={};
        QString operationId=generateOperationId("close_login",tmp);
        if(params.size()>=1)
        {
            auto result= params[0];
            setResult(operationId,QVariant::fromValue(result));
        }
        stopBlocking(operationId);
    }
}

void DatabaseManager::OnlineMsg(const QString &sender_id, const QString &receiver_id, const QString &msg_type,
                                const QString &content, const QString &media_url, const QString &send_time, const QString &is_deleted)
{

        QSqlQuery insert;
        insert.prepare("insert into private_message (sender_id,receiver_id,msg_type,content,media_url,send_time,is_deleted) values(:s,:r,:mt,:c,:mu,:st,:is)");
        insert.bindValue(":s",sender_id.toInt());
        insert.bindValue(":r",receiver_id.toInt());
        insert.bindValue(":mt",msg_type.toInt());
        insert.bindValue(":c",content);
        insert.bindValue(":m",0);
        insert.bindValue(":st",send_time);
        insert.bindValue(":is",is_deleted.toInt());
        if(insert.exec())
            return ;


}

void DatabaseManager::OnlineReq(const QString& id,const QString &user1, const QString &user2, const QString &user1_last_read_time,
                                const QString user2_last_read_time, const QString &who_request, const QString &relationship_type,
                                const QString &create_time, const QString &update_time, const QString &text_count)
{
    QSqlQuery query;
    query.prepare("select id from private_member where id=:id");
    query.bindValue(":id",id.toInt());
    query.exec();
    if(!query.next())
    {
        QSqlQuery insert;
        insert.prepare("insert into private_member (user1,user2,user1_last_read_time,user2_last_read_time,who_request,relationship_type,create_time,update_time,text_count) values(:u1,:u2,:ut1,:ut2,:w,:r,:c,:ut,:t,:i)");
        insert.bindValue(":u1",user1.toInt());
        insert.bindValue(":u2",user2.toInt());
        insert.bindValue(":ut1",user1_last_read_time);
        insert.bindValue(":ut2",user2_last_read_time);
        insert.bindValue(":w",who_request.toInt());
        insert.bindValue(":r",relationship_type.toInt());
        insert.bindValue(":c",create_time);
        insert.bindValue(":ut",update_time);
        insert.bindValue(":t",text_count.toInt());
        if(insert.exec())
            return ;
    }else {
        QSqlQuery update;
        update.prepare("update private_member (user1_last_read_time,user2_last_read_time,who_request,relationship_type,update_time,text_count) values(:ut1,:ut2,:w,:r,:ut,:t)");

        update.bindValue(":ut1",user1_last_read_time);
        update.bindValue(":ut2",user2_last_read_time);
        update.bindValue(":w",who_request.toInt());
        update.bindValue(":r",relationship_type.toInt());
        update.bindValue(":ut",update_time);
        update.bindValue(":t",text_count);
        if(update.exec())
            return ;
    }
    return ;


}



DatabaseManager::DatabaseManager()
{
    db=QSqlDatabase::addDatabase("QODBC");
    db.setHostName("127.0.0.1");
    db.setPort(3306);
    db.setDatabaseName("UserManageDSN");
    db.setUserName("root");
    db.setPassword("123456");

    if(!db.open())
    {
        qDebug()<<"Database open failed:"<<db.lastError().text();
    }
    this->socket=new QTcpSocket(this);
    this->socket->connectToHost(QHostAddress("127.0.0.1"),6666);//端口和ip根据自己定
    while(!this->socket->waitForConnected(5000)) {  // 等待5秒，若5秒内连接成功返回true，否则返回false
        qDebug() << "Connection timeout or failed";
    }
    qDebug()<<"could connect";

    // 绑定接收信号
    connect(socket, &QTcpSocket::readyRead, this, &DatabaseManager::recvServerMsg);
}

DatabaseManager::~DatabaseManager()
{
    if(db.isOpen())
    {
        db.close();
    }
}

QString DatabaseManager::generateOperationId(const QString& funcName, const QVector<QString>& params) {
    QStringList parts = {funcName};
    for (const auto& param : params) {
        parts.append(param);
    }
    return parts.join("|");
}

// 开始阻塞
void DatabaseManager::startBlocking(const QString& operationId, int timeoutMs) {
    QMutexLocker locker(&m_blockMutex);
    if (m_eventLoops.contains(operationId)) {
        return; // 避免重复阻塞
    }
    QEventLoop* loop = new QEventLoop(this);
    QTimer* timer = new QTimer(this);
    timer->setSingleShot(true);
    connect(timer, &QTimer::timeout, loop, &QEventLoop::quit);
    m_eventLoops[operationId] = loop;
    m_timers[operationId] = timer;
    timer->start(timeoutMs);
    locker.unlock();
    loop->exec();
    locker.relock();
    // 清理资源
    delete m_eventLoops[operationId];
    delete m_timers[operationId];
    m_eventLoops.remove(operationId);
    m_timers.remove(operationId);
}

// 解除阻塞
void DatabaseManager::stopBlocking(const QString& operationId) {
    QMutexLocker locker(&m_blockMutex);
    if (m_eventLoops.contains(operationId)) {
        QEventLoop* loop = m_eventLoops[operationId];
        QTimer* timer = m_timers[operationId];
        if (timer->isActive()) {
            timer->stop();
        }
        loop->quit();
    }
}

void DatabaseManager::setResult(const QString &operationId, const QVariant &result)
{
    QMutexLocker locker(&m_resultMutex);
    // 将结果存储到 m_results 中，以 operationId 作为键值
    m_results[operationId] = result;
}

template<typename T>
T DatabaseManager::getResult(const QString& operationId) {
    QMutexLocker locker(&m_resultMutex);
    if (m_results.contains(operationId)) {
        return m_results.take(operationId).value<T>();
    }
    return T(); // 返回默认值（结果不存在）
}



template<typename... Args>
bool DatabaseManager::send(const QString &funcName, Args&& ...args)
{
    // 转换参数为QString并序列化
    QString data = SERIALIZE(funcName, convertArg(args)...);
    return sendToServer(data);
}
